package org.jradweb.tools.generator.xml;

import java.io.File;
import java.io.IOException;

import javax.xml.parsers.ParserConfigurationException;

import org.apache.maven.plugin.logging.Log;
import org.jradweb.tools.generator.freemarker.Value;
import org.jradweb.tools.generator.utils.ConfigExistsException;
import org.jradweb.tools.generator.utils.LogImpl;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;

public class SpringServletOperator extends XmlOperator {

	public SpringServletOperator(File rootPath, String groupId,
			String artifactId, Log log) throws IOException,
			ParserConfigurationException, SAXException {
		super(rootPath, groupId, artifactId, log);
		File xmlFile = new File(rootPath.getAbsoluteFile()
				+ "/src/main/webapp/WEB-INF/spring-servlet.xml");
		if (!xmlFile.exists()) {
			String msg = "Spring config file not exits, please create it manually: "
					+ xmlFile.getAbsolutePath();
			this.getLog().error(msg);
			throw new IOException(msg);

		}
		this.setXmlFile(xmlFile);

		this.document = this.initDocument(this.getXmlFile());
	}

	public void addHandlerMapping(String controllerName, String pathName)
			throws Exception {
		Value controller = new Value(controllerName);
		Value path = new Value(pathName);

		Element beans = document.getDocumentElement();

		Node handlerMappingBean=this.getHandlerMappingBean();
		if(handlerMappingBean==null){
			String msg = "No bean \"handlerMapping\" found in file: "+this.getXmlFile();
			this.getLog().error(msg);
			throw new IOException(msg);
		}
		
		try {
			this.addMapping(handlerMappingBean, controller.getLowerCaseFirst(), path.getLowerCaseFirst());

		} catch (ConfigExistsException e) {
			this.getLog().warn(e.getMessage());
			return;
		}
		/*------------------------------------------------*/
		/* Save Document */
		/*------------------------------------------------*/
		this.saveDocument(XML_TYPE_SPRING);
		this.getLog().info(
				"Spring spring-servlet added mapping for controller \""
						+ controller + "\".");
	}
	private boolean addMapping(Node handlerMap,String name,String path) throws Exception{
		
		Node mappings=this.getChildNode(handlerMap, "property", "name", "mappings");
		if(mappings==null){
			String message="No \"property\" node in handlerMapping bean";
			throw new Exception(message);
		}
		
		Node props=this.getChildNode(mappings, "props", null, null);
		if(props==null){
			String message="No \"props\" node in \"props\" node of handlerMapping bean";
			throw new Exception(message);
		}
		
		Node oldNode=this.getChildNode(props, "prop", "key", path+"/*");
		if(oldNode!=null){
			String message="Mapping for path \""+path+"/*\" already exists!";
			throw new ConfigExistsException(message);
		}
		//create prop node
		Element newProp=this.document.createElement("prop");
		newProp.setAttribute("key", path+"/*");
		Text text=this.document.createTextNode(name+"Controller");
		newProp.appendChild(text);	
		
		props.appendChild(newProp);		
		
		return true;
	}
	
	private Node getChildNode(Node parent,String nodeName,String attributeName,String attributeValue){
		
		NodeList nodeList = parent.getChildNodes();
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node n = nodeList.item(i);
			if(n.getNodeName().equals(nodeName)){
				if(attributeName==null)
					return n;
				
				
				NamedNodeMap nnm=n.getAttributes();
				Node name=nnm.getNamedItem(attributeName);
				if(name!=null&&attributeValue==null){
					return  n;
				}
				else if(name!=null&&attributeValue.equals(name.getNodeValue())){
					return n;
				}
			}
		}
		
		return null;
	}
	private Node getHandlerMappingBean() {
		Element beans = document.getDocumentElement();

		NodeList beanList = beans.getChildNodes();
		for (int i = 0; i < beanList.getLength(); i++) {
			Node bean = beanList.item(i);

			if (bean.getNodeName().equals("bean")) {
				
				NamedNodeMap nnm = bean.getAttributes();
				for (int j = 0; j < nnm.getLength(); j++) {
					Node node = nnm.item(j);
					if (node.getNodeName().equals("id")
							&& node.getNodeValue().equals("handlerMapping")) {
						return bean;
					}

				}
			}
		}
		return null;
	}

	public static void main(String[] args) {
		SpringServletOperator opr;
		String name = "customer";
		try {
			File projectRootPath = new File("D:/workspace2/jradtest");
			opr = new SpringServletOperator(projectRootPath, "org.jradweb",
					"jradtest", new LogImpl(SpringServletOperator.class));
			opr.addHandlerMapping(name, name);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}
